xen/arm: Fix deadlock in gic_set_guest_irq()
The possible deadlock scenario is explained below:
non interrupt context: interrupt contex interrupt context
(CPU0): (CPU1):
vgic_distr_mmio_write() do_trap_irq() do_softirq()
| | |
vgic_disable_irqs() ... ...
| | |
gic_remove_from_queues() vgic_vcpu_inject_irq() vgic_vcpu_inject_irq()
| ... | |
| spin_lock(...) gic_set_guest_irq() gic_set_guest_irq()
| ... ... ...
| ... <----------------.---- spin_lock_irqsave(...) ...
| ... <----------------.-.---------------------------spin_lock_irqsave(...)
| ... . . Oops! The lock has already taken.
| spin_unlock(...) . .
| ... . .
gic_irq_disable() . .
... . .
spin_lock(...) . .
... . .
... <----------------. .
... <------------------.
...
spin_unlock(...)
Since the gic_remove_from_queues() and gic_irq_disable() called from
non interrupt context and they acquire the same lock as gic_set_guest_irq()
which called from interrupt context we must disable interrupts in these
functions to avoid possible deadlocks.
Change-Id: Ia354d87bb44418956e30cd7e49cc76616c359cc9
Signed-off-by: Oleksandr Tyshchenko <oleksandr.tyshchenko@globallogic.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>